home *** CD-ROM | disk | FTP | other *** search
/ Super PC 31 / Super PC 31 (Shareware).iso / spc / inter / speakf / fuente / readwave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-04  |  6.1 KB  |  236 lines

  1. /*
  2.  
  3.             Read .WAV audio files
  4.             
  5. */
  6.  
  7. #include "netfone.h"
  8.  
  9. int readWaveInit(HWND hwndApp, LPCLIENT_DATA d, LPSTR szFileName)
  10. {
  11.     MMCKINFO mmckinfoParent;
  12.     MMCKINFO mmckinfoSubchunk;
  13.     DWORD dwFmtSize;
  14.     char *err;
  15.  
  16. #define hmmio    d->mmioHandle
  17. #define pFormat    d->mmioFormat
  18.  
  19.     // Open the given file for reading using buffered I/O
  20.  
  21.     if (!(hmmio = mmioOpen(szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF))) {
  22.         MessageBox(hwndApp, rstring(IDS_T_OPEN_ERR), NULL, MB_OK | MB_ICONEXCLAMATION);
  23.         return FALSE;
  24.     }
  25.  
  26.     /* Locate a 'RIFF' chunk with a 'WAVE' form type to make 
  27.        sure it's a WAVE file. */ 
  28.      
  29.     mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  30.     if (mmioDescend(hmmio, (LPMMCKINFO) &mmckinfoParent, NULL, MMIO_FINDRIFF)) {
  31.         err = rstring(IDS_T_NOT_WAVE_FILE);
  32.         goto bail1;
  33.     }
  34.  
  35.     /* Now, find the format chunk (form type 'fmt '). It should be
  36.        a subchunk of the 'RIFF' parent chunk.  */
  37.      
  38.     mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
  39.     if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
  40.             MMIO_FINDCHUNK)) {
  41.         err = rstring(IDS_T_WAVE_FILE_CORRUPT);
  42.         goto bail1;
  43.     }
  44.  
  45.     /* Get the size of the format chunk, allocate and lock memory for it.  */
  46.     
  47.     dwFmtSize = mmckinfoSubchunk.cksize;
  48.     pFormat = (LPWAVEFORMAT) GlobalAllocPtr(GPTR, LOWORD(dwFmtSize));
  49.     if (pFormat == NULL) {
  50.         err = rstring(IDS_T_WAVE_NO_MEMORY);
  51.         goto bail1;
  52.     }
  53.  
  54.     /* Read the format chunk.  */
  55.     
  56.     if (mmioRead(hmmio, (HPSTR) pFormat, dwFmtSize) != (LONG) dwFmtSize) {
  57.         err = rstring(IDS_T_WAVE_NO_FORMAT);
  58.         goto bail2;
  59.     }
  60.  
  61.     /* Make sure it's a PCM file. */
  62.     
  63.     if (pFormat->wFormatTag != WAVE_FORMAT_PCM) {
  64.         err = rstring(IDS_T_NOT_PCM_FILE);
  65.         goto bail2;
  66.     }
  67.  
  68.     /* Ascend out of the format subchunk. */
  69.     
  70.     mmioAscend(hmmio, &mmckinfoSubchunk, 0);
  71.  
  72.     /* Find the data subchunk. */
  73.     
  74.     mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
  75.     if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
  76.             MMIO_FINDCHUNK)) {
  77.         err = rstring(IDS_T_WAVE_NO_DATA);
  78.         goto bail2;
  79.     }
  80.  
  81.     /* Get the size of the data subchunk. */
  82.     
  83.     d->mmioDataLeft = mmckinfoSubchunk.cksize;
  84.     if (d->mmioDataLeft == 0L) {
  85.         err = rstring(IDS_T_NO_DATA_IN_CHUNK);
  86.         goto bail2;
  87.     }
  88.     return TRUE;
  89.  
  90. bail2:    
  91.     GlobalFreePtr(pFormat);
  92. bail1:
  93.     mmioClose(hmmio, 0);
  94.     hmmio = NULL;
  95.     return FALSE;
  96. }
  97.  
  98. /*  READWAVENEXT  --  Fill a sound buffer with the next block
  99.                       of data from the WAVE file.  When the end
  100.                       of file is reached, FALSE is returned,
  101.                       otherwise the return is the number of samples
  102.                       stored in the sound buffer.  */
  103.  
  104. int readWaveNext(HWND hwnd, LPCLIENT_DATA d)
  105. {
  106.     LPSTR lpData;
  107.     DWORD lengthToRead, sampleRate;
  108.     int is8bit, chan, sampinc, nsamp;
  109.  
  110.     // If we've reached the end of file, return FALSE
  111.     
  112.     if (d->mmioDataLeft == 0) {
  113.         return FALSE;
  114.     }
  115.     
  116.     //    Force odd sample rates to the closest standard rate
  117.     
  118.     sampleRate = d->mmioFormat->nSamplesPerSec;
  119.     if (sampleRate < 9512) {
  120.         sampleRate = 8000;
  121.     } else if (sampleRate < 16537) {
  122.         sampleRate = 11025;
  123.     } else if (sampleRate < 33075) {
  124.         sampleRate = 22050;
  125.     } else {
  126.         sampleRate = 44100;
  127.     }  
  128.     
  129.     if (sampleRate == 8000) {
  130.         lengthToRead = currentInputSamples * d->mmioFormat->nBlockAlign;
  131.     } else {
  132.         lengthToRead = ((11025L * currentInputSamples * d->mmioFormat->nBlockAlign *
  133.                                 (sampleRate / 11025)) / 8000L);
  134.     }
  135.                                 
  136.     /* Allocate memory for the next block of waveform data. */
  137.     
  138.     lpData = GlobalAllocPtr(GPTR, lengthToRead);
  139.     if (lpData == NULL) {
  140.         MessageBox(hwnd, rstring(IDS_T_WAVE_MEM_ALLOC_ERR),
  141.            NULL, MB_OK | MB_ICONEXCLAMATION);
  142.         return FALSE;
  143.     }
  144.  
  145.     /* Read from the waveform data subchunk. */
  146.     
  147.     if ((lengthToRead = (DWORD) mmioRead(hmmio, (HPSTR) lpData, lengthToRead)) == 0) {
  148.         GlobalFreePtr(lpData);
  149.         return FALSE;
  150.     }
  151.     
  152.     is8bit = (d->mmioFormat->nBlockAlign / d->mmioFormat->nChannels) == 1;  
  153.     
  154.     /* Transform the data in the buffer into 11025 samples per
  155.        second 8 or 16 bit monaural, if necessary. */
  156.        
  157.     chan = d->mmioFormat->nChannels;
  158.     sampinc = sampleRate == 8000 ? 1 : ((int) (sampleRate / 11025));
  159.     nsamp = (int) (lengthToRead / (sampinc * chan * (is8bit ? 1 : 2)));
  160.              
  161.     if (sampleRate > 11025 || d->mmioFormat->nChannels != 1 || !is8bit) {
  162.         if (is8bit) {
  163.             int i;
  164.             BYTE FAR *ibuf = (BYTE FAR *) lpData,
  165.                  FAR *obuf = (BYTE FAR *) lpData;
  166.             
  167.             for (i = 0; i < nsamp; i++) {
  168.                 BYTE s = *ibuf;
  169.                 
  170.                 if (chan > 1) {
  171.                     short sum = s - 0x80;
  172.                     int j;
  173.                     BYTE FAR *cbuf = ibuf + 1;
  174.                     
  175.                     for (j = 1; j < chan; j++) {
  176.                         sum += (*cbuf++) - 0x80; 
  177.                     }
  178.                     s = 0x80 + (BYTE) (sum / chan);
  179.                 }
  180.                 *obuf++ = s;
  181.                 ibuf += sampinc * chan;
  182.             } 
  183.         } else {
  184.             int i;
  185.             short FAR *ibuf = (short FAR *) lpData,
  186.                   FAR *obuf = (short FAR *) lpData;
  187.             
  188.             for (i = 0; i < nsamp; i++) {
  189.                 short s = *ibuf;
  190.                 
  191.                 if (chan > 1) {
  192.                     long sum = s;
  193.                     int j;
  194.                     short FAR *cbuf = ibuf + 1;
  195.                     
  196.                     for (j = 1; j < chan; j++) {
  197.                         sum += *cbuf++; 
  198.                     }
  199.                     s = (short) (sum / chan);
  200.                 }
  201.                 *obuf++ = s;
  202.                 ibuf += sampinc * chan;
  203.             }
  204.             nsamp *= sizeof(short); 
  205.         }
  206.     }     
  207.        
  208.     /* Transfer the data to the sound buffer, converting the sampling
  209.        rate and encoding in u-law. */
  210.     
  211.     if (sampleRate != 8000) {
  212.         sampleRate = 11025;
  213.     }   
  214.     createSoundBuffer(lpData, nsamp, 1, sampleRate, (is8bit ? 1 : 2) * sampleRate,
  215.                       is8bit ? 1 : 2);
  216.     shipSoundBuffer(hwnd, d);
  217.     
  218.     GlobalFreePtr(lpData);
  219.     return (int) (nsamp / chan);
  220. }
  221.  
  222. /*    READWAVETERM  --  Terminate wave file input.  OK to call even
  223.                       if input isn't open.  */
  224.                       
  225. void readWaveTerm(LPCLIENT_DATA d)
  226. {
  227.     if (d->mmioHandle != NULL) {
  228.         mmioClose(d->mmioHandle, 0);
  229.         d->mmioHandle = NULL;
  230.     }
  231.     if (d->mmioFormat != NULL) {
  232.         GlobalFreePtr(d->mmioFormat);
  233.         d->mmioFormat = NULL;
  234.     }
  235. }            
  236.